package com.dianxin.smartpark.service.weChat.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.chinatelecom.response.common.CommonResponseBody;
import com.dianxin.acl.api.acl.AclFileRpcService;
import com.dianxin.acl.api.dto.SysFileDTO;
import com.dianxin.acl.api.qo.SysFileQO;
import com.dianxin.common.oss.properties.FileUploadResponse;
import com.dianxin.common.oss.util.MinioUtil;
import com.dianxin.smartpark.dao.dataobject.weChat.MobileRequest;
import com.dianxin.smartpark.service.weChat.WeChatService;
import io.netty.util.internal.StringUtil;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.imageio.stream.FileImageOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.AlgorithmParameters;
import java.security.SecureRandom;
import java.security.Security;
import java.util.*;

/**
 * @program: smart-park
 * @description: 微信小程序
 * @author: chenyong
 * @create: 2021-08-26 19:14
 */
@Service
public class WeChatServiceImpl implements WeChatService {

    private String appId = "wxe89a90a6cd32aa86";
    private String secret = "fb6b7fd9563379c0ea42044d68861eac";

    private String open_id;

    @Resource
    private MinioUtil minioUtil;
    @Resource
    private AclFileRpcService aclFileRpcService;

    /**
     * 通过code获取open_id
     * @Description:  通过code获取open_id
     * @Author: ChenYong
     * @Date: 2021/8/26 0026
     * @param code:
     * @Return: CommonResponseBody
     */
    @Override
    public CommonResponseBody sign(String code) {
        String data = "";
        String openid = "";
        CommonResponseBody commonResponseBody = new CommonResponseBody();
        if (StringUtil.isNullOrEmpty(code)) {
            commonResponseBody.setSuccess(false);
            commonResponseBody.setErrMsg("请求参数为空 +" + "code");
            commonResponseBody.setErrCode("111111");
            return commonResponseBody;
        }
        try {
            boolean check = (StringUtil.isNullOrEmpty(code)) ? true : false;
            if (check) {
                commonResponseBody.setSuccess(false);
                commonResponseBody.setErrMsg("code错误" + "code");
                commonResponseBody.setErrCode("111111");
                return commonResponseBody;
            }

            StringBuilder urlPath = new StringBuilder("https://api.weixin.qq.com/sns/jscode2session"); // 微信提供的API，这里最好也放在配置文件
            urlPath.append("?appid="+appId);
            urlPath.append("&secret="+secret);
            urlPath.append("&js_code="+code);
            urlPath.append("&grant_type="+"authorization_code");

            HttpClient client = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(urlPath.toString());
            // 发送消息和处理结果
            HttpResponse httpResponse = client.execute(httpGet);
            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                data = EntityUtils.toString(httpResponse.getEntity());
                openid = JSON.parseObject(data).getString("openid");
                if (StringUtil.isNullOrEmpty(openid)){
                    commonResponseBody.setSuccess(false);
                    commonResponseBody.setErrMsg("openid为空");
                    commonResponseBody.setErrCode("111111");
                    return commonResponseBody;
                }
            }else {
                commonResponseBody.setSuccess(false);
                commonResponseBody.setErrMsg("请求失败");
                commonResponseBody.setErrCode("111111");
                return commonResponseBody;
            }

            open_id = openid;
        } catch (Exception e) {
            commonResponseBody.setSuccess(false);
            commonResponseBody.setErrMsg("通过临时code获取微信信息错误 +" + "code= "+code);
            commonResponseBody.setErrCode("222");
            return commonResponseBody;
        }
        Map<String, Object> map = new HashMap<>();
        map.put("openid",open_id);
        commonResponseBody.setSuccess(true);
        commonResponseBody.setErrMsg("认证成功");
        commonResponseBody.setErrCode("000000");
        commonResponseBody.setData(map);
        return commonResponseBody;
    }


    /**
     * 通过code获取手机号
     * @Description:  通过code获取手机号
     * @Author: ChenYong
     * @Date: 2021/8/27 0027
     * @param mobileRequest:
     * @Return: CommonResponseBody
     */
    public CommonResponseBody getPhoneNumber(MobileRequest mobileRequest){
        CommonResponseBody commonResponseBody = new CommonResponseBody();
        String data = "";
        String session_key = "";
        try {
            StringBuilder urlPath = new StringBuilder("https://api.weixin.qq.com/sns/jscode2session"); // 微信提供的API，这里最好也放在配置文件
            urlPath.append("?appid="+appId);
            urlPath.append("&secret="+secret);
            urlPath.append("&js_code="+mobileRequest.getCode());
            urlPath.append("&grant_type="+"authorization_code");

            HttpClient client = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(urlPath.toString());
            // 发送消息和处理结果
            HttpResponse httpResponse = client.execute(httpGet);
            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                //if(httpResponse.getEntity()!=null){
                    data = EntityUtils.toString(httpResponse.getEntity());
                    session_key = JSON.parseObject(data).getString("session_key");
                    if (StringUtil.isNullOrEmpty(session_key)){
                        commonResponseBody.setSuccess(false);
                        commonResponseBody.setErrMsg("session_key为空");
                        commonResponseBody.setErrCode("111111");
                        return commonResponseBody;
                    }
               // }
            }else {
                commonResponseBody.setSuccess(false);
                commonResponseBody.setErrMsg("请求失败");
                commonResponseBody.setErrCode("111111");
                return commonResponseBody;
            }
            // 被加密的数据
            byte[] dataByte = Base64.getDecoder().decode(mobileRequest.getEncryptedData());
            // 加密秘钥
            byte[] keyByte = Base64.getDecoder().decode(session_key);
            // 偏移量
            byte[] ivByte = Base64.getDecoder().decode(mobileRequest.getIv());



            // 如果密钥不足16位，那么就补足.  这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");

            parameters.init(new IvParameterSpec(ivByte));
            cipher.init( Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, "UTF-8");
                commonResponseBody.setData(JSON.parseObject(result));
                commonResponseBody.setSuccess(true);
                commonResponseBody.setErrMsg("获取手机号成功");
                commonResponseBody.setErrCode("100000");
                return commonResponseBody;
            }
        } catch (Exception e) {
            commonResponseBody.setSuccess(false);
            commonResponseBody.setErrMsg("解密微信用户信息错误");
            commonResponseBody.setErrCode("111111");
            return commonResponseBody;
        }
        commonResponseBody.setSuccess(false);
        commonResponseBody.setErrMsg("请求失败");
        commonResponseBody.setErrCode("111111");
        return commonResponseBody;
    }

    /**
     * 获取小程序二维码
     * @Description:  获取小程序二维码
     * @Author: ChenYong
     * @Date: 2021/8/27 0027
     * @param mobileRequest:
     * @Return: CommonResponseBody
     */
    @Override
    public CommonResponseBody getWeChatCode(MobileRequest mobileRequest){
        CommonResponseBody dtoCommonResponseBody = new CommonResponseBody<>();


        try {
            SysFileQO sysFileQO = new SysFileQO();
            sysFileQO.setBusiType(9999);
            sysFileQO.setTenantId(mobileRequest.getTenantId());
            CommonResponseBody<List<SysFileDTO>> fileList = aclFileRpcService.getFileList(sysFileQO);
            if(fileList.getData().size()>0){
                dtoCommonResponseBody.setErrMsg("该租户已生成小程序二维码");
                dtoCommonResponseBody.setSuccess(false);
                dtoCommonResponseBody.setErrCode("9999");
                return dtoCommonResponseBody;
            }
            CommonResponseBody commonAccessToken = accessToken();
            String accessToken = String.valueOf(commonAccessToken.getData());
            String wxCodeURL = "https://api.weixin.qq.com/wxa/getwxacode?access_token="+accessToken ;
            URL url = new URL(wxCodeURL);
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.setRequestMethod("POST");// 提交模式
            // 发送POST请求必须设置如下两行
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
            // 发送请求参数
            JSONObject paramJson = new JSONObject();
            //paramJson.put("scene",mobileRequest.getTenantId());
            paramJson.put("path", "pages/qr-code/qr-code?tenantId="+mobileRequest.getTenantId()); //小程序暂未发布我没有带page参数
            printWriter.write(paramJson.toString());
            // flush输出流的缓冲
            printWriter.flush();
            //开始获取数据
            BufferedInputStream bis = new BufferedInputStream(httpURLConnection.getInputStream());

            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int num = 0;
            while ((num = bis.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, num);
            }
            byteArrayOutputStream.flush();
            byte[] bytes = byteArrayOutputStream.toByteArray();


            SysFileDTO sysFileDTO = new SysFileDTO();
            String filename = IdUtil.objectId()+".png";
            FileUploadResponse visitorPhotoUploadResponse = null;
            try{
                visitorPhotoUploadResponse = minioUtil.uploadFile(bytes,"wechat-photo",filename);
            } catch (Exception e){
                dtoCommonResponseBody.setErrMsg("文件上传失败");
                dtoCommonResponseBody.setSuccess(false);
                dtoCommonResponseBody.setErrCode("9999");
                return dtoCommonResponseBody;
            }

            if(visitorPhotoUploadResponse != null){
                sysFileDTO.setBusiType(9999);
                sysFileDTO.setFilePath(filename);
                sysFileDTO.setFileName(filename);
                sysFileDTO.setFileUrl(visitorPhotoUploadResponse.getUrlHttp());
                sysFileDTO.setFileExt("png");
                sysFileDTO.setBucketName("wechat-photo");
                sysFileDTO.setTenantId(mobileRequest.getTenantId());
                dtoCommonResponseBody = aclFileRpcService.insertSysFile(sysFileDTO);
            }


            /*BufferedOutputStream bos = null;
            FileOutputStream fos = null;
            File file = null;
            file = new File("D:/" + mobileRequest.getTenantId()+".png");
            if (!file.getParentFile().exists()){
                //文件夹不存在 生成
                file.getParentFile().mkdirs();
            }
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bytes);
            bos.close();
            fos.close();*/
            return dtoCommonResponseBody;
        } catch (Exception e) {
            dtoCommonResponseBody.setErrMsg("系统错误");
            dtoCommonResponseBody.setSuccess(false);
            dtoCommonResponseBody.setErrCode("9999");
            return dtoCommonResponseBody;
        }
    }


    /**
     * 获取小程序accessToken
     * @Description:  获取小程序accessToken
     * @Author: ChenYong
     * @Date: 2021/8/27 0027
     * @Return: CommonResponseBody
     */
    public CommonResponseBody accessToken() {
        String data = "";
        String accessToken = "";
        CommonResponseBody commonResponseBody = new CommonResponseBody();
        try {
            StringBuilder urlPath = new StringBuilder("https://api.weixin.qq.com/cgi-bin/token"); // 微信提供的API，这里最好也放在配置文件
            urlPath.append("?grant_type="+"client_credential");
            urlPath.append("&appid="+appId);
            urlPath.append("&secret="+secret);
            HttpClient client = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(urlPath.toString());
            // 发送消息和处理结果
            HttpResponse httpResponse = client.execute(httpGet);
            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                data = EntityUtils.toString(httpResponse.getEntity());
                accessToken = JSON.parseObject(data).getString("access_token");
                if (StringUtil.isNullOrEmpty(accessToken)){
                    commonResponseBody.setSuccess(false);
                    commonResponseBody.setErrMsg("accessToken为空");
                    commonResponseBody.setErrCode("111111");
                    return commonResponseBody;
                }
            }else {
                commonResponseBody.setSuccess(false);
                commonResponseBody.setErrMsg("请求失败");
                commonResponseBody.setErrCode("111111");
                return commonResponseBody;
            }
            commonResponseBody.setSuccess(true);
            commonResponseBody.setErrMsg("获取成功");
            commonResponseBody.setErrCode("000000");
            commonResponseBody.setData(accessToken);
            return commonResponseBody;
        } catch (Exception e) {
            commonResponseBody.setSuccess(false);
            commonResponseBody.setErrMsg("获取微信信息accessToken错误");
            commonResponseBody.setErrCode("222");
            return commonResponseBody;
        }
    }
}
